package com.shsxt.util.my;

import java.io.*;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;

import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.jdom.JDOMException;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.GetObjectRequest;
import com.shsxt.util.my.wx.MyPayCommonUtil;
import com.shsxt.util.my.wx.MyXMLUtil;
import com.shsxt.util.weixin.PayCommonUtil;
import com.shsxt.util.wx.GetWxOrderno;
import com.shsxt.util.wx.HttpClientConnectionManager;
import com.shsxt.util.wx.RequestHandler;

import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
 
/**
 * 林熙程工具类
 *
 */
@Component
public class MyUtil {
	 public static OSSClient ossClient = new OSSClient(MyParam.MYOSS_ENDPOINT, MyParam.MYOSS_ACCESSKEYID, MyParam.MYOSS_ACCESSKEYSECRET);
	/**
	 * 利用OSS上传缩放后的图片
	 * @param request
	 * @param session
	 * @param phoneNumber 唯一(手机号)
	 * @return
	 */
	 public static String headImage(HttpServletRequest request,HttpSession session,String phoneNumber) {
		 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
					request.getSession().getServletContext());
			if (multipartResolver.isMultipart(request)) {
				MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
				//获取所有文件
				Iterator<String> iter = multiRequest.getFileNames();
					//获取当前文件
					MultipartFile file = multiRequest.getFile((String) iter.next());
		// endpoint以杭州为例，其它region请按实际情况填写
		String endpoint = MyParam.MYOSS_ENDPOINT;
		// accessKey请登录https://ak-console.aliyun.com/#/查看
		String accessKeyId = MyParam.MYOSS_ACCESSKEYID;
		String accessKeySecret = MyParam.MYOSS_ACCESSKEYSECRET;
		String bucket = MyParam.MYOSS_BUCKET;
		String bucketLujin = MyParam.MYOSS_BUCKETLUJIN;
		// 创建OSSClient实例
		OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
		// 上传文件
		   CommonsMultipartFile cf= (CommonsMultipartFile)file; 
	        DiskFileItem fi = (DiskFileItem)cf.getFileItem(); 
	        File f = fi.getStoreLocation();
	        //命名图片
	        String fileName=imagesMyName(file, phoneNumber);
	        //把JSP上的图片上传到OSS
		ossClient.putObject(bucket, bucketLujin+fileName, f);
		changeSmall(fileName);
		
		// 关闭client
		ossClient.shutdown();
		return "成功";
			}
			return "失败";
	}	
	/**
	 * OSS设置图片名称
	 * @param file 文件名.格式
	 * @param phoneNumber 手机号
	 * @return 手机号+时间戳.格式
	 */
	public static String imagesMyName( MultipartFile file,String phoneNumber) {
		String fileName = file.getOriginalFilename();//储存地址
			//给图片命名手机好+时间戳
			fileName=phoneNumber+System.currentTimeMillis()+fileName.substring(fileName.lastIndexOf("."));
			return fileName;
	}	
	/**
	 * OSS替换成小图片,小图片再次上传覆盖大图片
	 * @param file
	 * @param phoneNumber
	 * @return
	 */
	public static void changeSmall( String fileName) {
	    GetObjectRequest req = new GetObjectRequest(MyParam.MYOSS_BUCKET, MyParam.MYOSS_BUCKETLUJIN+fileName);
	    req.setProcess(MyParam.MYOSS_STYLE);
	    ossClient.getObject(req, new File(MyParam.MYOSS_IMAGECASUAL));
	    ossClient.putObject(MyParam.MYOSS_BUCKET, MyParam.MYOSS_BUCKETLUJIN+fileName, new File(MyParam.MYOSS_IMAGECASUAL));
	 /*   删除OSS上的图片ossClient.deleteObject(MyParam.MYOSS_BUCKET,  MyParam.MYOSS_BUCKETLUJIN+fileName);*/
	}
	/**
	 * 支付 
	 * @param orderNumber
	 * @param type
	 * @param payType (支付宝,微信,余额)
	 * @return
	 */
	public Map<String, Object> myPay(String orderNumber ,String type ,String payType) {
		Map<String,Object> result=new HashMap<String,Object>();
		if(payType.equals("支付宝")){
			 result=myAlipay(orderNumber,type);
		}else if(payType.equals("微信")){
			 result=myWxinpay(orderNumber,type);
		}else if(payType.equals("余额")){
		}
		return result;
		
	}
	/**
	 * 退款
	 * @param orderNumber
	 * @param type
	 * @param payType
	 * @return
	 * @throws Exception 
	 */
	public Map<String, String> myRefund (HttpServletRequest request,HttpServletResponse response,String orderNumber ,String price ,String payType) throws Exception {
		Map<String, String> result=new HashMap<String,String>();
		if(payType.equals("支付宝")){
			 result=myAlipayRefundRequest(orderNumber,price);
		}else if(payType.equals("微信")){
			result=myWXRefundRequest( request, response,orderNumber,price);
		}else if(payType.equals("余额")){
		}
		return result;
		
	}
	/**
	 * 微信支付
	 * @param orderNumber
	 * @param type
	 * @return
	 */
	private Map<String, Object> myWxinpay(String orderNumber, String type) {
			  Map<String, Object> resultMap = new HashMap<String, Object>();
		         SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
		 		String price="1";
		         parameters.put("appid", "wx50a88bb93c045066");  
		         parameters.put("mch_id", "1464213402");  
		         parameters.put("nonce_str",MyPayCommonUtil.CreateNoncestr().substring(0, 9)+price);  
		         parameters.put("body", "会员卡");  
		         parameters.put("out_trade_no", orderNumber); //订单id
		         parameters.put("fee_type", "CNY");  
		         parameters.put("total_fee", price);  
		         parameters.put("spbill_create_ip","127.0.0.1");
		         parameters.put("notify_url", "http://139.196.102.135/controll/yzwxVip"); 
		         parameters.put("trade_type", "APP");  
		        //设置签名
		         String sign = MyPayCommonUtil.createSign("UTF-8",parameters);
		         parameters.put("sign", sign);
		       //封装请求参数结束
		         String requestXML = MyPayCommonUtil.getRequestXml(parameters);  
		        //调用统一下单接口
		         String result = MyPayCommonUtil.httpsRequest(MyParam.MYALIPAY_UNIFIEDORDERURL, "POST", requestXML);
		         System.out.println("\n"+result);
		         try {
		         /**统一下单接口返回正常的prepay_id，再按签名规范重新生成签名后，将数据传输给APP。参与签名的字段名为appId，partnerId，prepayId，nonceStr，timeStamp，package。注意：package的值格式为Sign=WXPay**/
		            Map<String, String> map = MyXMLUtil.doXMLParse(result);
		            SortedMap<Object, Object> parameterMap2 = new TreeMap<Object, Object>();  
		            parameterMap2.put("appid", MyParam.MYWXIN_APPID);  
		            parameterMap2.put("partnerid", MyParam.MYALIPAY_MCHID);  
		            parameterMap2.put("prepayid", map.get("prepay_id"));  
		            parameterMap2.put("package", "Sign=WXPay");  
		            //本来生成的时间戳是13位，但是ios必须是10位，所以截取了一下
		            parameterMap2.put("timestamp", Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0,10)));  
		            parameterMap2.put("noncestr", MyPayCommonUtil.CreateNoncestr());  
		            String sign2 = MyPayCommonUtil.createSign("UTF-8",parameterMap2);
		            parameterMap2.put("sign", sign2);  
		            resultMap.put("code","200");
		            resultMap.put("msg",parameterMap2);
		        } catch (JDOMException e) {
		            e.printStackTrace();
		        } catch (IOException e) {
		            e.printStackTrace();
		        }
		        return resultMap;
		    
	}
	/**
	 * 支付宝支付
	 * @param orderNumber 订单编号
	 * @param type 订单类型
	 * @return
	 */
	private Map<String, Object> myAlipay(String orderNumber, String type) {
		//实例化客户端
				Map<String,Object> map=new HashMap<String,Object>(); 
				AlipayClient alipayClient = new DefaultAlipayClient(MyParam.MYALIPAY_CLIENTADDRESS,MyParam.MYALIPAY_APPID, MyParam.MYALIPAY_APPPRIVATEKEY,"json","utf-8",MyParam.MYALIPAY_ALIPAYPUBLICKEY, "RSA2");
				//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
				AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
				//SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
				AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
				String price="0.01";
				model.setBody("寸芒");
				model.setSubject(type);
				model.setOutTradeNo(orderNumber);
				model.setTimeoutExpress("30m");
				model.setTotalAmount(price);
				model.setProductCode("QUICK_MSECURITY_PAY");
				request.setBizModel(model);
				request.setNotifyUrl(MyParam.MYALIPAY_NOTIFYURL);
				try {
				        //这里和普通的接口调用不同，使用的是sdkExecute
				        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
				        map.put("result", response.getBody());
				        return map;//就是orderString 可以直接给客户端请求，无需再做处理。
				    } catch (AlipayApiException e) {
				        e.printStackTrace();
				}		return null;
		
	}
	/**
	 * 支付宝退款
	 * @param orderNumber
	 * @param price
	 * @return
	 * @throws AlipayApiException
	 */
	 public  synchronized Map<String, String>  myAlipayRefundRequest(String orderNumber,String price) throws AlipayApiException{
			AlipayClient alipayClient = new DefaultAlipayClient(MyParam.MYALIPAY_CLIENTADDRESS,MyParam.MYALIPAY_APPID, MyParam.MYALIPAY_APPPRIVATEKEY,"json","utf-8",MyParam.MYALIPAY_ALIPAYPUBLICKEY, "RSA2");
	    	AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
	    	request.setBizContent("{" +
	    	"    \"out_trade_no\":\""+orderNumber+"\"," +
	    	"    \"refund_amount\":"+price+"," +
	    	"    \"refund_reason\":\"正常退款\"," +
	    	"    \"out_request_no\":\"HZ01RF001\"," +
	    	"    \"operator_id\":\"OP001\"," +
	    	"    \"store_id\":\"NJ_S_001\"," +
	    	"    \"terminal_id\":\"NJ_T_001\"" +
	    	"  }");
	    	Map<String, String> map=new HashMap<String,String>();
	    	AlipayTradeRefundResponse response = alipayClient.execute(request);
	    	if(response.isSuccess()){
	    		 map.put("result", "success");
	    		 return map;
	    	} else {
	    		 map.put("result", "failed");
	    		 return map;
	    	}
	    	
	    }
	 /**
	  * 微信退款
	  * @param request
	  * @param response
	  * @param orderNumber
	  * @param price
	  * @return
	  * @throws Exception
	  */
	 public  synchronized Map<String, String> myWXRefundRequest(HttpServletRequest request,HttpServletResponse response,String orderNumber,String price) throws Exception{
	        String filePath = MyParam.MYWX_CERT; //退款需要提供证书数据，所以需要根据证书路径读取证书
	        //需要退款的商户订单号，对应提交订单中的out_trade_no
	        Map<String,String> result = (Map<String, String>) wxRefund(request,response,orderNumber,price,filePath);

	        return result;
	    }
	 /**
	  * 微信退款具体步骤
	  * @param request
	  * @param response
	  * @param orderId
	  * @param total_fee
	  * @param path
	  * @return
	  * @throws Exception
	  */
	 public Map<String, String> wxRefund(HttpServletRequest request,HttpServletResponse response,
             String orderId,String total_fee ,String path) throws Exception{
		Map<String,String> result=new HashMap<String,String>(); 
		/*PageData pd = new PageData();
		pd = this.getPageData();*/
		String refundid = UUID.randomUUID().toString();
		String nonce_str = PayCommonUtil.CreateNoncestr();
		String appId="wx50a88bb93c045066";
		String shh="1464213402";
		String refund_fee=total_fee;
		/*-----  1.生成预支付订单需要的的package数据-----*/
		SortedMap<String, String> packageParams = new TreeMap<String, String>();
		packageParams.put("appid", appId);  
		packageParams.put("mch_id", shh);  
		packageParams.put("nonce_str", nonce_str);  
		packageParams.put("op_user_id", shh);  
		packageParams.put("out_trade_no", orderId);  
		packageParams.put("out_refund_no", refundid);  
		packageParams.put("total_fee",total_fee);  
		packageParams.put("refund_fee",refund_fee);  
		/*----2.根据package生成签名sign---- */
		RequestHandler reqHandler = new RequestHandler(request, response);
		reqHandler.init("wx50a88bb93c045066", "def3512409d71b787d13a86074913515", "PShYrhYPrScAu3ZSzK5KdfE6Eb6aLsYL");
		String sign = reqHandler.createSign(packageParams);
		
		/*----3.拼装需要提交到微信的数据xml---- */
		String xml="<xml>"
		+"<appid>"+appId+"</appid>"
		+ "<mch_id>"+shh+"</mch_id>"
		+ "<nonce_str>"+nonce_str+"</nonce_str>"
		+ "<op_user_id>"+shh+"</op_user_id>"
		+ "<out_trade_no>"+orderId+"</out_trade_no>"
		+ "<out_refund_no>"+refundid+"</out_refund_no>"
		+ "<refund_fee>"+refund_fee+"</refund_fee>"
		+ "<total_fee>"+total_fee+"</total_fee>"
		+ "<sign>"+sign+"</sign>"
		+"</xml>";
		
		 /*----4.读取证书文件,这一段是直接从微信支付平台提供的demo中copy的，所以一般不需要修改---- */
		 KeyStore keyStore  = KeyStore.getInstance("PKCS12");
		 FileInputStream instream = new FileInputStream(new File(path));
		 try {
		     keyStore.load(instream, shh.toCharArray());
		 } finally {
		     instream.close();
		 }
		 // Trust own CA and all self-signed certs
		 SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, shh.toCharArray()).build();
		 // Allow TLSv1 protocol only
		 SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,
		         SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		 CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
		
		 /*----5.发送数据到微信的退款接口---- */
		 String url="https://api.mch.weixin.qq.com/secapi/pay/refund";
		 HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
		 httpost.setEntity(new StringEntity(xml, "UTF-8"));
		 HttpResponse weixinResponse = httpClient.execute(httpost);
		 String jsonStr = EntityUtils.toString(weixinResponse.getEntity(), "UTF-8");
		 System.err.println(jsonStr);
		 Map map = GetWxOrderno.doXMLParse(jsonStr);
		 if("success".equalsIgnoreCase((String) map.get("return_code"))){
		     System.err.println("退款成功");
		     result.put("returncode", "ok");
		     result.put("returninfo", "退款成功");
		 }else{
		     System.err.println("退款失败111");
		     result.put("returncode", "error");
		     result.put("returninfo", "退款失败");
		 }
		
		return result;
		
		}
	

}